/*
 * Copyright (c) 2008, Xiong Yingfei, the University of Tokyo All rights
 * reserved.
 */
package ac.jp.u_tokyo.SyncLib.language;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import ac.jp.u_tokyo.SyncLib.util.Pair;

public class SyncRef extends SyncBody
{

	Program _program;

	Map<String, Const> _argMap = new HashMap<String, Const>();

	String _name;

	public SyncRef(int line, Program program, String name)
	{
		super(line);
		_program = program;
		_name = name;
	}

	public void addArg(String name, Const value)
	{
		_argMap.put(name, value);
	}


	@Override
	public String writeInitializeFactory(Appendable sb,
			VarNameGenerator generator, ConstMapper constMap)
			throws EvaluationFailedException, IOException
	{
		SyncDecl decl = getSyncDecl();

		List<Pair<String, Const>> args = new LinkedList<Pair<String, Const>>();
		for (Pair<String, Const> para : decl)
		{
			Const value = _argMap.get(para.getValue1());
			if (value != null)
				args.add(new Pair(para.getValue1(), value));
			else
			{
				value = para.getValue2();
				if (value != null)
					args.add(new Pair(para.getValue1(), value));
				else
					throw new ParameterNotAssigned(getLine(), para.getValue1());
			}
		}

		String varName = generator.getNextName();
		sb.append(Program.getSyncFactoryFullName()).append(" ").append(varName)
				.append(" = ").append(Program.syncNameToMethodName(_name))
				.append("(");
		Iterator<Pair<String, Const>> it = args.iterator();
		if (it.hasNext())
		{
			it.next().getValue2().write(sb, constMap);
		}
		while (it.hasNext())
		{
			sb.append(", ");
			it.next().getValue2().write(sb, constMap);
		}
		sb.append(");\n");
		return varName;
	}

	private SyncDecl getSyncDecl() throws ReferenceNotFoundException
	{
		SyncDecl decl = _program.getSyncDecl(_name);
		if (decl == null) throw new ReferenceNotFoundException(getLine(), _name);
		return decl;
	}

	@Override
	public int getParaCount() throws EvaluationFailedException
	{
		SyncDecl decl = getSyncDecl();
		return decl.getBody().getParaCount();
	}

	
}
